Object는 데이터들을 묶는 구조이다. 순서없는 컬렉션이라고도 볼 수 있다. property는 원시값, 객체, 함수를 가질 수 있다.

선언 방법

1
2
3
4
5
var person = new Object();
var person = {};
var person = { name: "junho", age: 29 };
person.name;
person['name'];

객체 생성

  • 팩토리 패턴

특정 객체 생성 과정 추상화

1
2
3
4
5
6
7
8
9
10
11
function CreatePerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function() {
alert(this.name);
}
return o;
}

var person = CreatePerson('junho', 28);

그러나, 객체가 어떤 타입인지 알 수 없는 단점이 존재한다. 무조건 Object일것이기 때문에

  • 생성자 패턴
1
2
3
4
5
6
7
8
9
10
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
alert(this.name);
}
}

var person = new Person('junho', 28); // new를 사용해야 한다!
Person('junho', 28); // window 객체에 해당 프로퍼티 들이 추가된다.

new 연산자의 과정

  1. 객체 생성
  2. 생성자의 this값에 객체 할당
  3. 객체에 프로퍼티 추가.
  4. 새 객체 반환

생성자 패턴에도 문제가 있는데, 아래처럼 여러 Person을 생성할 경우, this.sayName의 경우 똑같은 일을 함에도 불구하고 내부적으로는 this.sayName = new Function() 이 실행되어 Function 인스턴스가 2개 존재하게 된다.

1
2
3
4
// 위 예제에서 계속
var person = new Person('junho', 28);
var person2 = new Person('lia', 24);
alert(person.sayName == person2.sayName); // false

위 문제를 해결하기 위한 생성자 패턴은 prototype을 배운 후에 더 공부해보자(Prototype과 상속 포스팅참조)

프로퍼티

  • 데이터 프로퍼티
    • [[Configurable]] : 프로퍼티의 삭제, 속성 변경 할 수 있는 여부 (default true)
    • [[Enumerable]] : for_in 루프에서 해당 프로퍼티 반환할 수 있음(default true)
    • [[Writable]] : 값 바꿀 수 있음 (default true)
    • [[value]] : 프로퍼티의 실제 데이터 값 (default undefined)

프로퍼티 저장시, 위 4가지 값이 할당 된다. 데이터 프로퍼티를 셋팅하기 위해서 Object.defineProperty를 이용하면 된다.

1
2
3
4
5
6
7
8
var person = {};
Object.defineProperty(person, 'name', {
writable : false,
value : 'junho'
});
alert(person.name); // junho
person.name = 'lia';
alert(person.name); // junho
  • 접근자 프로퍼티
    • [[Configurable]] : 프로퍼티의 삭제, 속성 변경 할 수 있는 여부 (default true)
    • [[Enumerable]] : for_in 루프에서 해당 프로퍼티 반환할 수 있음(default true)

getter/setter 함수로 구성된다. 프로퍼티 값 바꿀 때 부수적 절차 필요한 경우 사용된다. 데이터 프로퍼티와는 달리 실제 데이터가 없다. 정의 위해서는 반드시 Object.defineProperty를 이용해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var book = { _year : 2004, edition: 1 };
Object.defineProperty(book, "year", {
get: function() {
return this._year;
},
set: function(newValue) {
if(newValue > 2004) {
this._year = newValue;
this.edition += (newValue - 2004);
}
},
enumerable: true,
configurable: true
});

book.year = 2005;
alert(book.edition); // 2

getter만 지정시 읽기전용이되며, setter만 지정시 프로퍼티를 읽을때 undefined를 반환한다.

객체 반복

객체에는 in을 쓰고, 배열에는 of 를 쓰자. 배열의 인덱스는 number지만, in을 쓸 경우 string형으로 리턴되기 때문이다. 겪어보지는 않았지만, 루프문이 무작위로 도는 경우도 있다고 한다.

체인
열오

체인열오!

1
2
3
4
var people = {'name':'junho', 'old': 5};
for(key in people) {
console.log('key : ' + key + 'value : ' + people[key]);
}

in 연산자에선 [[Enumberable]] 프로퍼티가 true 인 프로퍼티들이 모두 리턴된다. 프로토타입의 변수들 역시 리턴된다.

Reference

https://medium.com/@bluesh55/javascript-prototype-이해하기-f8e67c286b67

http://unikys.tistory.com/320

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/

프론트엔드 개발자를 위한 Javascript - 니콜라스 자카스